package com.bf.hotpoint.repository.mongo;

import static org.springframework.data.mongodb.core.query.Criteria.where;

import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.query.Update.Position;
import org.springframework.stereotype.Repository;

import sun.security.krb5.internal.rcache.ReplayCache;

import com.bf.hotpoint.domain.Message;
import com.bf.hotpoint.domain.Reply;
import com.mongodb.WriteResult;

import static org.springframework.data.mongodb.core.query.Query.query;
import static org.springframework.data.mongodb.core.query.Update.update;


@Repository
public class MessageMongoRepository
{
	@Autowired
	private MongoTemplate mongoTemplate;
	
	public void addMessage(Message message)
	{
		String collectionName = mongoTemplate.getCollectionName(Message.class);
		
		if(message != null){
			mongoTemplate.save(message);
		}
	}
	
	public boolean deleteMessage(String messageId)
	{
		WriteResult writeResult = mongoTemplate.remove(query(where("id").is(messageId)), Message.class);
		return writeResult.getN() <= 0 ? false : true;
	}
	
	public boolean updateMessage(Message message)
	{
		WriteResult writeResult = null;
		if(message != null){
			if(mongoTemplate.findById(message.getMessageId(), Message.class) != null)
			{
				writeResult = mongoTemplate.updateFirst(query(where("id").is(message.getMessageId())), update(message.getMessageId(),message), Message.class);
			}
		}
		if(writeResult == null){
			return false;
		}
		return writeResult.getN() <= 0 ? false : true;
	}
	
	
	public List<Message> getMessages(int lastIndex,int pageSize,String subject,Date startSearchTimeDate)
	{
		return mongoTemplate.find(query(where("subject").is(subject).and("isAvailable").is(true).and("availableTime").lt(new Date()).and("publishTime").lt(startSearchTimeDate)).with(new Sort(Sort.Direction.DESC, "publishTime")).skip(lastIndex).limit(pageSize), Message.class);
	}
	
	public List<Message> getMessages(int lastIndex,int pageSize,String subject)
	{
		return mongoTemplate.find(query(where("subject").is(subject).and("isAvailable").is(true).and("availableTime").lt(new Date())).with(new Sort(Sort.Direction.DESC, "publishTime")).skip(lastIndex).limit(pageSize), Message.class);
	}
	
	public List<Message> getMessages(int lastIndex,int pageSize,Point point,double distance,Date startSearchTimeDate)
	{
		//bug of mongodb   if add location condition of find.and order by desc      skip will be wrong    ,it's away skip to last
		//return mongoTemplate.find(query(where("location").near(point).maxDistance(distance).and("availableTime").gt(new Date())).with(new Sort(Sort.Direction.DESC, "publishTime")).skip(pageNumber*pageSize).limit(pageSize), Message.class);
		return mongoTemplate.find(query(where("location").near(point).maxDistance(distance).and("availableTime").gt(new Date()).and("publishTime").lt(startSearchTimeDate)).with(new Sort(Sort.Direction.DESC, "publishTime")), Message.class);
	}
	
	public List<Message> getMessages(int lastIndex,int pageSize,Point point,double distance)
	{
		//bug of mongodb   if add location condition of find.and order by desc      skip will be wrong    ,it's away skip to last
		//return mongoTemplate.find(query(where("location").near(point).maxDistance(distance).and("availableTime").gt(new Date())).with(new Sort(Sort.Direction.DESC, "publishTime")).skip(pageNumber*pageSize).limit(pageSize), Message.class);
		return mongoTemplate.find(query(where("location").near(point).maxDistance(distance).and("availableTime").gt(new Date())).with(new Sort(Sort.Direction.DESC, "publishTime")), Message.class);
	}
	
	public List<Message> getMessages(List<String> messageIds)
	{
		return mongoTemplate.find(query(where("messageId").in(messageIds).and("availableTime").gt(new Date())), Message.class);
	}
	
	public Message getMessage(String messageId)
	{
		return mongoTemplate.findOne(query(where("messageId").in(messageId).and("availableTime").gt(new Date())), Message.class);
	}
	
	public Reply getReply(String replyId)
	{
		return mongoTemplate.findOne(query(where("reply.id").is(replyId)), Reply.class);
	}
	
	public List<Message> getMessagesAvailableTimeLessThisTime(Date date)
	{
		Query q = new Query();
		q.addCriteria(where("availableTime").lt(date));
		return mongoTemplate.find(q, Message.class);
	}
	
	public void deleteMessagesAvailableTimeLessThisTime(Date date)
	{
		Query q = new Query();
		q.addCriteria(where("availableTime").lt(date));
		mongoTemplate.remove(q, Message.class);
	}
	
	public boolean addReplyToMessageByMessageId(String messageId,Reply reply)
	{
		WriteResult writeResult = mongoTemplate.updateFirst(query(where("_id").is(messageId)), new Update().push("replies", reply), Message.class);
		if(writeResult == null){
			return false;
		}
		return writeResult.getN() <= 0 ? false : true;
	}
}